/*
 * 
 * Proj. Wireless - UFRN
 * 
 */

package metodologia;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.crypto.*;

public class SerializarObjetoCryptografado <E>{
    private E entrada;
    private SecretKey key;
    private Cipher cipher;
    private SealedObject sealedObject;
    
    public SerializarObjetoCryptografado() throws Exception{
        entrada = null;
    }
    
    public void serializar(E dados, String caminho) {
        try {
            encrypt(dados);
        } catch (IOException ex) {
            Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalBlockSizeException ex) {
            Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchPaddingException ex) {
            Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
        }
        
	FileOutputStream arq = null;
	ObjectOutputStream out = null;
        
	try {
            //arquivo no qual os dados vao ser gravados
            arq = new FileOutputStream(caminho);

            //objeto que vai escrever os dados
            out = new ObjectOutputStream(arq);

            //escreve todos os dados
            out.writeObject(key);
            out.writeObject(sealedObject);
	} catch (IOException ex) {
            ex.printStackTrace();
	} finally {
            try {
                arq.close();
                out.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
	}
    }
    
    public E deserializar(String caminho) {
	FileInputStream arqLeitura = null;
	ObjectInputStream in = null;
	try {
            //arquivo onde estao os dados serializados
            arqLeitura = new FileInputStream(caminho);

            //objeto que vai ler os dados do arquivo
            in = new ObjectInputStream(arqLeitura);

            //recupera os dados
            //entrada = (E)in.readObject();
            key = (SecretKey)in.readObject();
            sealedObject = (SealedObject)in.readObject();
            try {
                entrada = decrypt();
            } catch (NoSuchAlgorithmException ex) {
                Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NoSuchPaddingException ex) {
                Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvalidKeyException ex) {
                Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalBlockSizeException ex) {
                Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
            } catch (BadPaddingException ex) {
                Logger.getLogger(SerializarObjetoCryptografado.class.getName()).log(Level.SEVERE, null, ex);
            }
	} catch (ClassNotFoundException ex) {
            ex.printStackTrace();
	} catch (IOException ex) {
            ex.printStackTrace();
	} finally {
            try {
                arqLeitura.close();
                in.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
	}
 
	return entrada;
    }
    
    public void encrypt(E dados) throws IOException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{
      
        key = KeyGenerator.getInstance("DES").generateKey();
        
        cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
 
        sealedObject = new SealedObject((Serializable)dados, cipher);
    }
    
    public E decrypt() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException{
        String algorithmName = sealedObject.getAlgorithm();
        cipher = Cipher.getInstance(algorithmName);
        cipher.init(Cipher.DECRYPT_MODE, key);
 
        E elemento = (E) sealedObject.getObject(cipher);
        return elemento;
    }

}
